﻿#pragma once

// Inner Fire 游戏引擎库
// 简单的MESH
//
// Copyright (c) 2023 by 尔西大帝. All rights reserved.
//
// 用于读取简单的模型
//
// Author: 尔西大帝
// Email: 2670613871@qq.com
// Created: 2024-11-19

#include <DirectXCollision.h>
#include <dx_core/dx_core.h>
#include <unordered_map>

namespace ifire {

/*
 * Mesh类
 */
struct SimpleSubmesh {
  SimpleSubmesh() = default;
  SimpleSubmesh(
      UINT _index_count, UINT _start_index_location, INT _base_vertex_location)
      : IndexCount(_index_count)
      , StartIndexLocation(_start_index_location)
      , BaseVertexLocation(_base_vertex_location){};

  UINT IndexCount = 0;
  UINT StartIndexLocation = 0;
  INT BaseVertexLocation = 0;
  DirectX::BoundingBox Bounds;
};

typedef SimpleSubmesh SubmeshGeometry;

struct SimpleMesh {
  // 几何体的名称
  std::string Name;

  // 顶点内存
  ComPtr<ID3DBlob> VertexBufferCPU = nullptr;
  ComPtr<ID3D12Resource> VertexBufferGPU = nullptr;
  ComPtr<ID3D12Resource> VertexBufferUploader = nullptr;

  // 索引内存
  ComPtr<ID3DBlob> IndexBufferCPU = nullptr;
  ComPtr<ID3D12Resource> IndexBufferGPU = nullptr;
  ComPtr<ID3D12Resource> IndexBufferUploader = nullptr;

  // 与缓冲区相关的数据
  UINT VertexByteStride = 0;
  UINT VertexBufferByteSize = 0;
  DXGI_FORMAT IndexFormat = DXGI_FORMAT_R16_UINT;
  UINT IndexBufferByteSize = 0;

  // 一个标准结构体下面的子结构体。
  std::unordered_map<std::string, SimpleSubmesh> DrawArgs;


  D3D12_VERTEX_BUFFER_VIEW VertexBufferView() const {
    D3D12_VERTEX_BUFFER_VIEW view = {};
    view.BufferLocation = VertexBufferGPU->GetGPUVirtualAddress();
    view.StrideInBytes = VertexByteStride;
    view.SizeInBytes = VertexBufferByteSize;
    return view;
  }

  D3D12_INDEX_BUFFER_VIEW IndexBufferView() const {
    D3D12_INDEX_BUFFER_VIEW view = {};
    view.BufferLocation = IndexBufferGPU->GetGPUVirtualAddress();
    view.Format = IndexFormat;
    view.SizeInBytes = IndexBufferByteSize;
    return view;
  }

  // 等待数据上传之后，就可以释放这些内存。
  void DisposeUploaders() {
    VertexBufferUploader = nullptr;
    IndexBufferUploader = nullptr;
  }
};

typedef SimpleMesh MeshGeometry;

} // namespace ifire